package com.sample.snl.frontend.LexicalAnalysis;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;

public class LexicalAnalyser {
    public static List<String> errors = new ArrayList<>();
    static Logger LOG = LoggerFactory.getLogger(LexicalAnalyser.class);
    public Reader reader;
    static int line = 1;
    static int column = 0;
    static int getMeFirst = -1;

    public LexicalResult getResult(Reader reader) throws IOException {
        errors = new ArrayList<>();
        LexicalResult result = new LexicalResult();
        List<Token> list = new ArrayList<>();
        if (reader == null) {
            errors.add("Input stream must not be not null.");
            result.setErrors(errors);
            result.setTokenList(list);
            return result;
        }
        this.reader = reader;
        Token token = getToken();
        while (token != null) {
            list.add(token);
            token = getToken();
        }
        result.setTokenList(list);
        result.setErrors(errors);
        return result;
    }

    private Token getToken() throws IOException {
        Automaton automaton = new Automaton(reader);
        //LOG.trace("Invoking getToken method...");
        int ch = automaton.getChar();
        while (ch != -1) {
            automaton.stringBuilder.append((char) ch);
            automaton.state.HandleCharacter(ch);
            if (automaton.gotToken) {
                return automaton.token;
            }
            ch = automaton.getChar();
        }

        if (automaton.state == automaton.InDotState) {
            automaton.token = new Token(line, column, TokenType.EOF, ".");
            //LOG.debug("Recognized Token:" + automaton.token);
            return automaton.token;
        }
        if (automaton.state != automaton.StartState) {
            errors.add("[error] in " + "line " + line + "column " + column);
        }
        return null;
    }


    /*public static void main(String[] args) {
        InputStream in = LexicalAnalyser.class.getClassLoader().getResourceAsStream("sample.snl");
        LexicalAnalyser lexer = new LexicalAnalyser();
        try {
            LexicalResult result = lexer.getResult(new InputStreamReader(in));
            if (result.getErrors().size() == 0) {
                List<Token> list = result.getTokenList();
                System.out.println();
                if (list.size() > 0) {
                    System.out.print("[ Ln:Col ]|[Semantics]| Lexical message \n");
                    System.out.print("---------+--------------+----------\n");
                }
                for (Token t : list) {
                    System.out.printf("[%3d:%-3d]|[%10s]|%12s\n", t.line, t.column, t.meaning, t.type.getStr());
                }
                if (list.size() > 0) {
                    System.out.print("---------+--------------+----------\n");
                    System.out.print("[ Line:Column ]|[Semantics]| Lexical message \n");
                }
            } else {
                System.out.print("[ Ln:Col ]|[Semantics]| Lexical message \n");
                result.getErrors().forEach(System.err::println);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }*/
}
